package com.wngbms;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import rx.Observable;
import rx.Observer;
import rx.functions.Action1;

import java.util.concurrent.locks.LockSupport;

@Slf4j
public class FirstDemo {

    /**
     * 06:28:04.957 [hystrix-expGrp-1] INFO com.wngbms.CommandHelloWorld - ===> do run
     * 06:28:04.958 [hystrix-expGrp-1] INFO com.wngbms.FirstDemo - <<<<<<< win
     * 06:28:04.958 [hystrix-expGrp-1] INFO com.wngbms.FirstDemo - on next win
     * 06:28:04.959 [hystrix-expGrp-1] INFO com.wngbms.FirstDemo - completed
     * 06:28:04.959 [main] INFO com.wngbms.FirstDemo - <<<<<< win
     */
    @Test
    public void reactiveExe() {
        CommandHelloWorldExe cmd = new CommandHelloWorldExe();
        Observable<String> observable = cmd.observe();

        // non-blocking
        observable.subscribe(new Action1<String>() {
            @Override
            public void call(String s) {
                log.info("<<<<<<< {}", s);
            }
        });

        observable.subscribe(new Observer<String>() {
            @Override
            public void onCompleted() {
                log.info("completed");
            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                log.info("on next {}", s);
            }
        });

        observable.subscribe((v) -> {
            log.info("output {}", v);
        });

        observable.subscribe((v) -> {
            log.info("output {}", v);
        }, (exp) -> {
            log.error("", exp);
        });

        // blocking
        String single = observable.toBlocking().single();
        log.info("<<<<<< {}", single);

        LockSupport.park();
    }

    /**
     * Rather than converting a HystrixCommand into an Observable using the methods described above,
     * you can also create a HystrixObservableCommand
     * that is a specialized version of HystrixCommand meant to wrap Observables.
     * A HystrixObservableCommand is capable of wrapping Observables
     * that emit multiple items,
     * whereas ordinary HystrixCommands, even when converted into Observables, will never emit more than one item.
     *
     * In such a case, instead of overriding the run method with your command logic (as you would with an ordinary HystrixCommand),
     * you would override the <i>construct method</i> so that it returns the Observable you intend to wrap.
     *
     * To obtain an Observable representation of the HystrixObservableCommand, use one of the following two methods:
     *
     * observe() — returns a “hot” Observable
     * that subscribes to the underlying Observable immediately,
     * though because it is filtered through a ReplaySubject you are not in danger of losing any items that it emits before you have a chance to subscribe to the resulting Observable
     *
     * toObservable() — returns a “cold” Observable
     * that won’t subscribe to the underlying Observable
     * until you subscribe to the resulting Observable
     */
    @Test
    public void reactiveCmd() {
        CommandHelloWorldCmd cmd = new CommandHelloWorldCmd();
        /**
         * 会开始执行
         * 06:40:14.161 [RxIoScheduler-2] INFO com.wngbms.CommandHelloWorldCmd -  ----> do call
         */
        Observable<String> observable = cmd.observe();

        /**
         * 06:44:52.288 [main] INFO com.wngbms.FirstDemo - output <<< hello
         */
        observable.subscribe((v) -> {
            log.info("output <<< {}", v);
        });

        /**
         * 要重新创建 否则报错
         * CommandHelloWorldCmd command executed multiple times - this is not permitted.
         */
        cmd = new CommandHelloWorldCmd();
        /**
         * 不会产生输出
         */
        Observable<String> observable1 = cmd.toObservable();
        /**
         * 06:46:26.037 [RxIoScheduler-2] INFO com.wngbms.CommandHelloWorldCmd -  ----> do call
         * 06:46:26.037 [RxIoScheduler-2] INFO com.wngbms.FirstDemo - output <<< hello
         */
        observable1.subscribe((v) -> {
            log.info("output <<< {}", v);
        });

        LockSupport.park();
    }


    @Test
    public void fallbackExe() {
        String execute = new CommandHelloFailureExe().execute();
        log.info("output <<< {}", execute);
    }

    @Test
    public void fallbackCmd() {

    }

}
